package main

import (
	"fmt"
	"sort"
)

type Person struct {
	Name    string
	Gender  int8
	Address string
}

func (this *Person) String() string {
	//return "姓名"+this.Name+"性别:"+(this.Gender==1?"男":"女")+"地址:"+this.Address
	return ""
}

func main() {
	declareMap()
	judge()
	commonUse()
	deleteMap()
	sortMap()
	currentcyMap()
}

func declareMap() {

	//第一种声明map的方式
	var mapps map[string]Person
	mapps = make(map[string]Person) //不使用make默认初始化为nil
	mapps["zhangsan"] = Person{Name: "张三", Gender: 1, Address: "湖北武汉"}
	mapps["lisi"] = Person{Name: "李四", Gender: 1, Address: "湖北宜昌"}
	mapps["wangwu"] = Person{Name: "王五", Gender: 1, Address: "湖北恩施"}
	for k, v := range mapps {
		fmt.Println("key=", k, "value=", v)
	}

	//第二种声明map的方式
	maps := map[string]Person{
		"zhangsan": Person{Name: "张三", Gender: 1, Address: "湖北武汉"},
		"lisi":     Person{Name: "李四", Gender: 1, Address: "湖北宜昌"},
		"wangwu":   Person{Name: "王五", Gender: 1, Address: "湖北恩施"},
	}

	//循环遍历
	for k, v := range maps {
		fmt.Println("key=", k, "value=", v)
	}

}

func judge() {
	maps := map[string]string{
		"name":    "张三",
		"gender":  "男",
		"address": "湖北",
	}
	//判断map中是否存在
	if v, ok := maps["name"]; ok {
		fmt.Println(v)
		fmt.Println(maps["gender"])
		fmt.Println(maps["address"])
	} else {
		fmt.Println("NOT FOUND")
	}
}

func commonUse() {
	maps := map[string]interface{}{
		"Students": map[string]Person{
			"student01": Person{Name: "张三", Gender: 1, Address: "湖北武汉"},
			"student02": Person{Name: "李四", Gender: 1, Address: "湖北武汉"},
			"student03": Person{Name: "王五", Gender: 1, Address: "湖北武汉"},
		},
		"Teacher": map[string]Person{
			"teacher01": Person{Name: "张三", Gender: 1, Address: "湖北武汉"},
			"teacher02": Person{Name: "张三", Gender: 1, Address: "湖北武汉"},
			"teacher03": Person{Name: "张三", Gender: 1, Address: "湖北武汉"},
		},
	}
	for k, v := range maps {
		fmt.Println("key=", k, "value=", v)
	}
}

func deleteMap() {
	maps := map[string]string{
		"name":   "张三",
		"gender": "男",
	}
	delete(maps, "name")
	fmt.Println("删除后的map", maps)
}

func sortMap() {
	maps := map[string]int{
		"unix":         0,
		"python":       1,
		"go":           2,
		"javascript":   3,
		"testing":      4,
		"philosophy":   5,
		"startups":     6,
		"productivity": 7,
		"hn":           8,
		"reddit":       9,
		"C++":          10,
	}

	for k, v := range maps {
		fmt.Println("key:", k, "value:", v)
	}

	var keys []string
	for k := range maps {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		fmt.Println("Key:", k, "Value:", maps[k])
	}
}

//go语言中的Map不是并发安全的
//因为map为引用类型，所以即使函数传值调用，参数副本依然指向映射m, 所以多个goroutine并发写同一个映射m， 写过多线程程序的同学都知道，对于共享变量，资源，并发读写会产生竞争的， 故共享资源遭到破坏
//并发安全问题需要锁 或者 使用队列
func currentcyMap() {
	//这段代码就很容易出错
	/*c := make(map[string]int)
	for i := 0; i < 100; i++ {
		go func() {
			for j := 0; j < 1000000; j++ {
				c[fmt.Sprintf("%d", j)] = j
			}
		}()
	}*/
}
